package com.violet.uaa.server.security.handler;

import cn.hutool.json.JSONUtil;
import com.violet.auth.client.util.JwtTokenUtil;
import com.violet.common.entity.LoginUser;
import com.violet.common.response.Result;
import com.violet.uaa.server.login.entity.LoginLog;
import com.violet.uaa.server.login.service.LoginLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.OAuth2Request;
import org.springframework.security.oauth2.provider.TokenRequest;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * 类说明: 登录成功返回前端数据
 * successHandler和failureHandler是Spring Security中两个较为强大的用来处理登录成功和失败的回调函数，通过它们两个我们就可以自定义一些前后端数据的交互。
 *
 * @author wqf
 * @date 2023/7/10 9:40
 */
@Slf4j
@Component
public class VioSuccessHandler implements AuthenticationSuccessHandler {

    @Resource
    private LoginLogService loginLogService;
    @Resource
    private JwtTokenUtil jwtTokenUtil;
    @Resource
    private DefaultTokenServices tokenServices;

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        log.info("登陆成功，当前用户信息：{}", JSONUtil.toJsonStr(loginUser));
        try {
            LoginLog loginLog = new LoginLog();
            loginLog.setUsername(loginUser.getUsername());
            loginLog.setIp(request.getRemoteAddr());
            loginLog.setOperateTime(LocalDateTime.now());
            loginLog.setRemark("用户登陆");
            loginLogService.save(loginLog);
            log.error("=========用户登陆日志记录成功========{}", JSONUtil.toJsonStr(loginLog));
        } catch (Exception e) {
            log.error("=========用户登陆日志记录失败========", e);
        }

        TokenRequest tokenRequest = new TokenRequest(Collections.emptyMap(), "client_id", Collections.singleton("scope"), null);
        OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(null);
        // 根据需要填充
        // 创建 OAuth2Authentication 对象
        OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);
        // 生成访问令牌
        OAuth2AccessToken accessToken = tokenServices.createAccessToken(oAuth2Authentication);

        response.setCharacterEncoding(StandardCharsets.UTF_8.name());
        response.setHeader("Content-Type", "application/json;charset=UTF-8");
        try (ServletOutputStream ous = response.getOutputStream()) {
            //返回token
            Map<String, Object> result = new HashMap<>();
            result.put("sub", loginUser.getUsername());
            Result<Object> responseData = Result.succeed("登陆成功", accessToken.getValue());
            response.setStatus(HttpStatus.OK.value());
            ous.write(JSONUtil.toJsonStr(responseData).getBytes(StandardCharsets.UTF_8));
        }
    }
}
